Virtual constructors
I recently added a new feature for a more generic handling of abstract data types: virtual constructors. This is actually a collection of three new features:
- Virtual
SIZEOF()
expressions that now return the size of the deriving type of an object, and not its static type. This is used to allocate memory to store copies of abstract objects. This departs from previous behaviour, which was equivalent to C++'s nativesizeof()
. - The builtin
COPY_RTTI(value, dest)
operation copies the type tag of an abstract value into a designated memory address, so that it will be recognised as the same deriving type as the supplied value by virtual functions and theTYPE()
expression. - Virtual constructors:
obj.VIRTUAL{...}
will call a constructor on the deriving type ofobj
with the given arguments.
With all these features combined, we can, for example, clone any object in a generic way, without knowing its deriving type or size:
[AbstractT: TYPE] clone(ptr: AbstractT #\) AbstractT \
{
clone ::= <AbstractT \>(std::heap::alloc_raw(SIZEOF#(*ptr)));
COPY_RTTI(*ptr, clone); // init memory to TYPE(*ptr)
clone->VIRTUAL{*ptr}; // copy constructor
= clone;
}
This allows us to write clean code that does not need to know any deriving types, and even works on non-abstract types, as COPY_RTTI
on non-abstract types is a no-op (since they have no type tag).
Now we no longer need any # ABSTRACT clone() THIS - std::Dyn
methods in abstract base classes, which keeps deriving classes lean, and no longer forces the cloning method to use any particular allocator or container type, as this can now be implemented in a black-box manner.